<%
' +----------------------------------------------------------------------
' | POPASP [ ASP MVC ]
' +----------------------------------------------------------------------
' | Copyright (c) 2016 http://popasp.com All rights reserved.
' +----------------------------------------------------------------------
' | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
' +----------------------------------------------------------------------
' | Author: popasp <1737025626@qq.com>
' +----------------------------------------------------------------------
' 反射类，用于分析 POPASP_XXX文件或者 XXXAction控制器文件或者 XXXMODEL 数据模型文件的变量、方法、继承
Class POPASP_REJECTION
	private reg
	
	' 判断className类中是否有method方法
	Public Function Variable_Exists( className,variable )
		dim dict
		set dict = Parse( className )
		Variable_Exists  = dict("public_vars").Exists( LCase(variable) )
	End Function
	
	' 判断className类中是否有method方法
	Public Function Method_Exists( ByVal className,ByVal method )
		dim dict
		set dict = Parse( className )
		Method_Exists  = dict("public_method").Exists( LCase(method) )
	End Function

	' 解析类的变量与方法及继承关系
	Public Function Parse( ByVal className )
		dim content,m,modelFile,rejFile,dict		
		if POP_MVC.dRejection.Exists( className ) Then
			Set Parse =  POP_MVC.dRejection(className)
		Else
			rejFile = className		
			if NOT POP_MVC.isPopasp(className) AND NOT POP_MVC.isAction(className) Then rejFile = POP_MVC.getModelRunName(className) & "Model"
			rejFile = APP_PATH & "/Runtime/Class/" & LCase(rejFile) & ".rejection.asp"
			
			if POP_MVC.file.isExists( rejFile ) AND is_empty(C_("APP_DEBUG")) Then
				content = POP_MVC.file_get_contents( rejFile )
				set Parse = js_decode( content )
				set POP_MVC.dRejection( className ) = Parse
			Else				
				if POP_MVC.isPopasp( className ) Then	'核心类
					content = POP_MVC.get_import_asp(className)		
				Elseif POP_MVC.isAction(className) Then	'控制器类					
					if className = C_("SYSTEM_MODULE") & "Action" Then
						content = POP_MVC.asp_get_contents( POP_MVC.mvc_dir & "Tpl/" & className & ".class.asp" )
					else						
						content = POP_MVC.asp_get_contents( APP_PATH & "/Controller/" & className & ".class.asp" )
					end if					
				else 	'默认情况下为模型类，只输入表名即名
					modelFile = POP_MVC.getModelDstPath(className)
					if Not POP_MVC.file.isExists(  modelFile  ) Then
						set m = M_(className)
						set m = nothing
					End If
					if POP_MVC.file.isExists(  modelFile  ) Then
						content = POP_MVC.asp_get_contents(modelFile)
					End If
				end If
				
				set dict = ParseContent( content )
				
				if POP_MVC.isAction(className) AND C_("TMPL_CACHE_ACTION") <> "" Then	'控制器类
					POP_MVC.Dict.Push dict("public_method") , LCase( C_("TMPL_CACHE_ACTION") ) ,C_("TMPL_CACHE_ACTION")
				end if
				set Parse = dict		
				call js_put_contents(rejFile,Parse)
				set POP_MVC.dRejection( className ) = Parse
				set dict = nothing
			End If		
		End If		
	End Function
	
	' 从类的文本内容中获取解析内容
	' 包括{"private_vars":{"小写的变量名":"实际变量名"},"public_vars":{...},"private_method":{"小写的方法名称":"Function或者Sub"},"public_method":{...}}
	Public Function ParseContent( content )
		dim dict,extends
		set dict = D_
		set dict = ParseVariables( content )
		
		set dict = POP_MVC.dict.Merge(ParseVariables( content ) , ParseMethod( content ) )
		
		
		
		extends = ParseExtends(content)
		if Not isEmpty(extends) Then dict("extends") =  ParseExtends(content)	

		

		
		set ParseContent = dict		
		set dict = Nothing
	End Function
	
	' 从类的文本内容中获取解析后的继承类名，比如后台控制器多继承 CommonAction
	Public Function ParseExtends( content )
		dim matches	
		if POP_MVC.String.reg_test(content , "^\s*Class\s+\w+\s*'\s*Extends\s+(\w+)" , "im") Then
			set matches = POP_MVC.reg.Execute( content )
			ParseExtends = matches(0).SubMatches(0)
			set matches = nothing
		End If			
	End Function
	
	' 从类的文本内容中获取解析后的方法，包括Private方法与Public方法
	' 返回的是Dictionary对象。{"private_method":{"小写的方法名称":"Function或者Sub"},"public_method":{...}}
	Public Function ParseMethod( content )
		dim dict
		set dict = D_
		set dict("private_method") = ParseMethod_( "^\s*(?:private)\s+(sub|function|property\s+let|property\s+get|property\s+set)\s+\[?(\w+)\]?\s*" ,content )
		set dict("public_method") = ParseMethod_( "^\s*(?:public)?(?:\s+default)?\s+(sub|function|property\s+let|property\s+get|property\s+set)\s+\[?(\w+)\]?\s*" ,content  )
		set ParseMethod = dict
		set dict = nothing
	End Function
	
	' 从类的文本内容中获取解析后的变量，包括Private变量与Public变量
	' 返回的是Dictionary对象。{"private_vars":{"小写的变量名":"实际变量名"},"public_vars":{...}}
	Public Function ParseVariables( content )
		dim dict
		set dict = D_
		set dict("private_vars") = ParseVariables_( "^\s*(?:private)\s+(?!sub|property|function)([\w ,\[\]]+)\s*('.*)?$" ,content )
		set dict("public_vars") = ParseVariables_( "^\s*(?:public)\s+(?!sub|property|function)([\w ,\[\]]+)\s*('.*)?$" ,content )
		set ParseVariables = dict
		set dict = nothing
	End Function
	
	'解析类中的类变量，pattern为正则匹配，content为类的文本内容
	Private Function ParseVariables_( byref pattern,byRef content ) 'className,method
		dim matches,i,j,str,arr,temp,key,cnt
		dim dict
		set dict = D_
		if POP_MVC.String.reg_test(content,pattern,"gim") Then			
			set matches = POP_MVC.reg.Execute( content  )
			for i = 0 to matches.count-1
				str = matches(i).submatches(0)
				arr = split( str, "," )
				cnt = ubound(arr)
				for j = 0 to cnt
					temp = arr(j)
					key = temp
					key = POP_MVC.ltrim( key, "[" )
					key = POP_MVC.ltrim( key, "]" )
					key = LCase(key)
					dict( key ) = temp
				next
			next			
		End If
		set ParseVariables_ = dict
		set dict = nothing
		set matches = nothing
	End Function
	
	'解析类中的方法，pattern为正则匹配，content为类的文本内容
	Private Function ParseMethod_( byref pattern ,byref content ) 'className,method
		dim matches,i
		dim dict
		set dict = D_
		if POP_MVC.String.reg_test(content,pattern,"gim") Then
			set matches = POP_MVC.reg.Execute ( content )
			for i = 0 to matches.count-1
				dict( LCase(matches(i).submatches(1)) ) = matches(i).submatches(1)
			next			
		End If
		set ParseMethod_ = dict
		set dict = nothing
		set matches = nothing
	End Function	
	
	Private Sub Class_Initialize
		set reg = POP_MVC.reg
	End Sub
	
	Private sub Class_Terminate
		'set reg = Nothing
	End Sub
End Class
%>